package com.me.libgdx_test;

import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector3;

public class ClassObjectSpellDungeon extends AbstractClassObjectDungeon{
	private ClassDungeonSpell spell;
	private boolean upgrade_grumpkin = false;
	private boolean upgrade_totem = false;
	private boolean spell_used;
	private int spell_damage;
	private int mana_spark_divisor;
	ClassObjectSpellDungeon(){
		this.spell = null;
	}
	ClassObjectSpellDungeon(ClassDungeonSpell spell){
		this.spell = spell;
	}
	public ClassDungeonSpell get_spell_info(){
		return spell;
	}
	public void refund_mana(ClassCharacterPlayer player, int spell_cost){
		player.set_player_variable("current_mana", player.get_player_variable("current_mana")+spell_cost);
		spell_used = false;
	}
	public boolean pick_up_spell(ClassCharacterPlayer player){
		for(int i = 0; i < player.get_spells().length;i++){
			if(player.get_spells()[i].get_spell_info() == null ){
				player.get_spells()[i] = this;
				return true;
			}
		}
		return false;
	}
	public void upgrade_totem(){
		upgrade_totem = true;
	}
	public void upgrade_grumpkin(){
		upgrade_grumpkin = true;
	}
	public int get_spell_cost(ClassCharacterPlayer player){
		return player.get_class_mods().playerSpellMod.get_cost(this);
	}
	public float get_spell_strength(ClassCharacterPlayer player){
		float amnesia = (player.get_contracted_mod("Amnesia") || player.get_attack_mod("Amnesia"))?.75f:1;
		amnesia += player.get_class_mods().playerSpellMod.spell_strength;
		return amnesia;
	}
	//                     current player object      the cursor position     the board objects
	public void use_spell(ClassCharacterPlayer player, ClassCursorAt cursorOn, ClassPlaceObjects objects, 
			CopyOnWriteArrayList<ClassAnimationIterator> animations, CopyOnWriteArrayList<ClassAnimationString> animationtext, ClassAnimationTextureLoader animation_loader){
		Random random = new Random(System.currentTimeMillis());
		//These things should always be put before the spell is cast
		player.get_class_mods().playerSpellMod.pre_cast_modifiers(player, this);
		int spell_cost = player.get_class_mods().playerSpellMod.get_cost(this);
		
		ClassLogDisplay logger = new ClassLogDisplay("ClassObjectSpellDungeon");
		logger.print(spell.Name);
		float amnesia = get_spell_strength(player);
		mana_spark_divisor = player.get_class_mods().playerSpellMod.mana_spark_divisor;
		spell_used = false;
		spell_damage = 0;
		if (player.get_player_variable("current_mana") >= spell_cost && player.get_class_mods().playerSpellMod.can_cast_spell(this)){
			spell_used = true;
			player.set_player_variable("current_mana", player.get_player_variable("current_mana")-spell_cost);
			if(spell.Name == "Blood"){
				if(player.get_contracted_mod("Blood")){
					player.set_contracted_mod("Blood", false);
				}else if(!player.get_contracted_mod("Blood")){
					player.set_contracted_mod("Blood", true);
					player.set_contracted_mod("Mind", false);
				}
			}
			if(spell.Name == "Converter"){
				if(player.get_player_variable("gold")>=5){
					player.set_player_variable("gold", player.get_player_variable("gold")-5);
					player.set_player_variable("current_health", 5*player.get_player_variable("level"));
					player.cure_all();
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "EndWall"){
				ClassObjectTotem totem = objects.totem_there(cursorOn.location);
				if(objects.get_dungeon(cursorOn.location)==1 || totem!=null){
					//Remove wall and totem if applicable
					objects.set_dungeon(cursorOn.location, 0);
					objects.remove_totem(totem);
					recalc_totems(player,objects);
					animations.add(new ClassAnimationIterator(cursorOn.location,
							animation_loader.return_animation_by_name("animation_blackx"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
				}else{
					refund_mana(player, spell_cost);
				}	
			}
			if(spell.Name == "FireBall"){
				if(cursorOn.get_object_type()==1){
					//If the enemy is dead, we have to remove it
					spell_damage = cursorOn.enemy.current_health - 
							get_spell_damage("FireBall", cursorOn, player, objects);
					
					animationtext.add(
							new ClassAnimationString(""+spell_damage, cursorOn.enemy.get_location(), 20, 14, Color.BLUE));
							//cursorOn.enemy.attack_spell((int)(4*player.level),amnesia);
					if(cursorOn.enemy.current_health<1){
						add_kill_count(cursorOn.enemy, player);
						objects.remove_enemy(cursorOn.enemy);
						player.add_enemy_exp(cursorOn.enemy);
						animations.add(new ClassAnimationIterator(cursorOn.enemy.location,
								animation_loader.return_animation_by_name("animation_blackcross"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
					}else{
						animations.add(new ClassAnimationIterator(cursorOn.enemy.location,
								animation_loader.return_animation_by_name("animation_spellfireball"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
					}
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "FirstStrike"){
				//Remember that you dont get blood pools from killing enemies with magic
				if(!player.get_contracted_mod("First Strike")){
					//player.set_player_variable("first_strike", 1);
					player.set_contracted_mod("First Strike", true);
					animations.add(new ClassAnimationIterator(player.location,
							animation_loader.return_animation_by_name("animation_blackx"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "Grumpkin"){
				if(cursorOn.get_object_type()==3 && cursorOn.pickup.get_pickup_info().get_item_type()==8){
					//If the enemy is dead, we have to remove it
					ClassCharacterEnemy enemy = new ClassCharacterEnemy(objects.get_game_vars().enemyObjects[17]);
					enemy.set_location(cursorOn.location);
					enemy.set_modifiers(objects.get_game_vars().modObjects);
					player.get_class_mods().playerEnemyMod.set_enemy(enemy);
					
					if(!upgrade_grumpkin){
						enemy.set_level(0, 1);
					}else{
						enemy.set_level(10, 1);
					}
					objects.get_placed_things().add(cursorOn.location);
					objects.add_enemy(enemy);
					objects.remove_pickup(cursorOn.pickup);
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "Heal"){
				if(player.get_player_variable("current_health")<player.get_max_health()){
					player.set_player_variable("current_health", 
							player.get_player_variable("current_health") + 3*player.get_player_variable("level"));
					player.cure_heal();
					animations.add(new ClassAnimationIterator(player.location,
							animation_loader.return_animation_by_name("animation_spellheal"),ClassAnimationIterator.Constants.ANIMATION_SHORT,1));
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "KillProtect"){
				if(!player.get_contracted_mod("Extra Life")){
					player.set_contracted_mod("Extra Life",true);
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "Might"){
				if(!player.spell_bonus){
					player.add_temp_spell_bonus(.25f);
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "Petrify"){
				if(cursorOn.get_object_type()==1){
					objects.remove_enemy(cursorOn.enemy);
					objects.set_dungeon(cursorOn.location, 1);
					animations.add(new ClassAnimationIterator(cursorOn.location,
							animation_loader.return_animation_by_name("animation_blackx"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "Poison"){
				//If the cursor is on an enemy and the enemy isn't already poisoned...
				if(cursorOn.get_object_type()==1 && !cursorOn.enemy.get_contracted_mod("Poison")){
					cursorOn.enemy.set_contracted_mod("Poison", true);
				}else{
					refund_mana(player, spell_cost);
				}
				
			}
			if(spell.Name == "Reveal"){
				if(objects.get_shroud().size()>0){
					int count = 3;
					while(objects.get_shroud().size()>0 && count > 0){
						Point remove_location = objects.get_shroud().get(random.nextInt(objects.get_shroud().size()));
						objects.remove_shroud(remove_location);
						animations.add(new ClassAnimationIterator(remove_location,
								animation_loader.return_animation_by_name("animation_blackx"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
						count--;
					}
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "Summon"){
				ClassCharacterEnemy blank_enemy = null;
				Point empty_spot = null;
				Point test_point = new Point();
				for(ClassCharacterEnemy enemy: objects.get_enemies()){
					if(enemy.level == player.level){
						blank_enemy = enemy;
						break;
					}
				}
				for(int y = player.get_location().y-1; y<player.get_location().y+2;y++){
					for(int x = player.get_location().x-1; y<player.get_location().x+2;x++){
						test_point.move(x, y);
						if(objects.in_dungeon(test_point) && objects.nothing_there().contains(test_point)){
							empty_spot = new Point(test_point);
							break;
						}
					}
				}
				if(blank_enemy!=null && empty_spot!=null){
					blank_enemy.set_location(empty_spot);
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "Teleport"){
				if(cursorOn.get_object_type()==1){
					ArrayList<Point> nothing_array = objects.nothing_there();
					cursorOn.enemy.set_location(new Point(nothing_array.get(random.nextInt(nothing_array.size()))));
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "ManaSpark"){
				if(cursorOn.get_object_type()==1){
					//If the enemy is dead, we have to remove it
					spell_damage = cursorOn.enemy.current_health - 
							get_spell_damage("ManaSpark", cursorOn, player, objects);
					
					animationtext.add(
							new ClassAnimationString(""+spell_damage, cursorOn.enemy.get_location(), 20, 14, Color.BLUE));
							//cursorOn.enemy.attack_spell((int)(player.get_player_variable("current_mana")),amnesia);
					if(cursorOn.enemy.current_health<1){
						add_kill_count(cursorOn.enemy, player);
						objects.remove_enemy(cursorOn.enemy);
						player.add_enemy_exp(cursorOn.enemy);
						animations.add(new ClassAnimationIterator(cursorOn.enemy.location,
								animation_loader.return_animation_by_name("animation_blackcross"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
					}else{
						animations.add(new ClassAnimationIterator(cursorOn.enemy.location,
								animation_loader.return_animation_by_name("animation_spellshock"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
					}
					player.set_player_variable("current_mana",player.get_player_variable("current_mana")/mana_spark_divisor);
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "Totem"){
				if(cursorOn.get_object_type()==3 && cursorOn.pickup.get_pickup_info().get_item_type()==8){
					//If the enemy is dead, we have to remove it
					objects.remove_pickup(cursorOn.pickup);
					ClassObjectTotem totem = new ClassObjectTotem(objects.get_game_vars().totemObjects[0],upgrade_totem);
					totem.set_location(cursorOn.location);
					objects.add_totem(totem);
					recalc_totems(player,objects);
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "Klondike"){
				if(cursorOn.get_object_type()==1){
					//If the enemy is dead, we have to remove it
					spell_damage = cursorOn.enemy.current_health - 
							get_spell_damage("Klondike", cursorOn, player, objects);
					
					animationtext.add(
							new ClassAnimationString(""+spell_damage, cursorOn.enemy.get_location(), 20, 14, Color.BLUE));
							//cursorOn.enemy.attack_spell((int)(player.get_player_variable("gold")/4),amnesia);
					if(cursorOn.enemy.current_health<1){
						add_kill_count(cursorOn.enemy, player);
						objects.remove_enemy(cursorOn.enemy);
						player.add_enemy_exp(cursorOn.enemy);
						animations.add(new ClassAnimationIterator(cursorOn.enemy.location,
								animation_loader.return_animation_by_name("animation_blackcross"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
					}else{
						animations.add(new ClassAnimationIterator(cursorOn.enemy.location,
								animation_loader.return_animation_by_name("animation_ripplered"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
					}
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "Nexus"){
				if(cursorOn.get_object_type()==1){
					//If the enemy is dead, we have to remove it
					spell_damage = cursorOn.enemy.current_health - 
							get_spell_damage("Nexus", cursorOn, player, objects);
					
					animationtext.add(
							new ClassAnimationString(""+spell_damage, cursorOn.enemy.get_location(), 20, 14, Color.BLUE));
							//cursorOn.enemy.attack_spell((int)(objects.get_enemies().size()*1.5),amnesia);
					if(cursorOn.enemy.current_health<1){
						add_kill_count(cursorOn.enemy, player);
						objects.remove_enemy(cursorOn.enemy);
						player.add_enemy_exp(cursorOn.enemy);
						animations.add(new ClassAnimationIterator(cursorOn.enemy.location,
								animation_loader.return_animation_by_name("animation_blackcross"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
					}else{
						animations.add(new ClassAnimationIterator(cursorOn.enemy.location,
								animation_loader.return_animation_by_name("animation_ripplered"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
					}
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "Affinity"){
				if(cursorOn.get_object_type()==3 && cursorOn.pickup.get_pickup_info().get_item_type()==8){
					//Remove the blood pool
					objects.remove_pickup(cursorOn.pickup);
					//Mark the area as having something new in it
					objects.get_placed_things().add(cursorOn.location);
					
					ClassObjectPickupDungeon item;
					switch(random.nextInt(7)){
						//This makes a shop...
						case 1:
							ClassObjectShopDungeon shop;
							ArrayList<ClassDungeonShop> shop_items = new ArrayList<ClassDungeonShop>();
							ArrayList<ClassDungeonShop> upgradeable_used = new ArrayList<ClassDungeonShop>();

							while(shop_items.size()<3){
								//ClassDungeonShop temp_holder = objects.get_game_vars().shopObjects[random.nextInt(objects.get_game_vars().shopObjects.length)];
								//while(!temp_holder.actual_shop || (temp_holder.upgradeable && upgradeable_used.contains(temp_holder))){
								//	temp_holder = objects.get_game_vars().shopObjects[random.nextInt(objects.get_game_vars().shopObjects.length)];
								//}
								//if(temp_holder.upgradeable){upgradeable_used.add(temp_holder);}
								
								//All the objects will be experience
								ClassDungeonShop temp_holder = objects.get_game_vars().shopObjects[5];
								shop_items.add(new ClassDungeonShop(temp_holder));
							}
							shop = new ClassObjectShopDungeon(shop_items,objects.get_game_vars().player_level,objects.get_shop_discount());
							
							shop_items.clear();
							shop.set_location(cursorOn.location);
							objects.get_shops().add(shop);
							animations.add(new ClassAnimationIterator(cursorOn.location,
									animation_loader.return_animation_by_name("animation_blackx"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
							break;
						//This makes atk
						case 2:
							item = new ClassObjectPickupDungeon(objects.get_game_vars().iconObjects[0]);
							item.set_location(cursorOn.location);
							objects.get_pickups().add(item);
							animations.add(new ClassAnimationIterator(cursorOn.location,
									animation_loader.return_animation_by_name("animation_ballrotateviolet"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
							break;
						//This makes health
						case 3:
							item = new ClassObjectPickupDungeon(objects.get_game_vars().iconObjects[1]);
							item.set_location(cursorOn.location);
							objects.get_pickups().add(item);
							animations.add(new ClassAnimationIterator(cursorOn.location,
									animation_loader.return_animation_by_name("animation_ballrotatered"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
							break;
						//This makes mana
						case 4:
							item = new ClassObjectPickupDungeon(objects.get_game_vars().iconObjects[3]);
							item.set_location(cursorOn.location);
							objects.get_pickups().add(item);
							animations.add(new ClassAnimationIterator(cursorOn.location,
									animation_loader.return_animation_by_name("animation_ballrotateblue"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
							break;
						//This makes gold
						case 5:
							item = new ClassObjectPickupDungeon(objects.get_game_vars().iconObjects[5]);
							item.set_location(cursorOn.location);
							objects.get_pickups().add(item);
							animations.add(new ClassAnimationIterator(cursorOn.location,
									animation_loader.return_animation_by_name("animation_ballrotategold"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
							break;
						//Else pull the object reference from the placed objects holder
						default:
							objects.get_placed_things().remove(cursorOn.location);
							animations.add(new ClassAnimationIterator(cursorOn.location,
									animation_loader.return_animation_by_name("animation_xalt"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
							break;
							
					}
				}else{
					refund_mana(player, spell_cost);
				}
			}
			if(spell.Name == "Chains"){
				if(!player.get_contracted_mod("Chains")){
					player.set_contracted_mod("Chains", true);
					animations.add(new ClassAnimationIterator(player.get_location(),
							animation_loader.return_animation_by_name("animation_spellshock"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
				}else{
					refund_mana(player, spell_cost);
				}
			}
			//Increases levelup stats
			if(spell.Name == "Knowledge"){
				animations.add(new ClassAnimationIterator(player.get_location(),
						animation_loader.return_animation_by_name("animation_xalt"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
			}
			//Increases medals earned at the end of the game
			if(spell.Name == "Medal"){
				animations.add(new ClassAnimationIterator(player.get_location(),
						animation_loader.return_animation_by_name("animation_xalt"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
			}
			if(spell.Name == "Mind"){
				if(player.get_contracted_mod("Mind")){
					player.set_contracted_mod("Mind", false);
				}else if(!player.get_contracted_mod("Mind")){
					player.set_contracted_mod("Mind", true);
					player.set_contracted_mod("Blood", false);
				}
			}
			if(spell.Name == "Sigil"){
				if(cursorOn.get_object_type()==1){
					//If the enemy is dead, we have to remove it
					spell_damage = cursorOn.enemy.current_health - 
							get_spell_damage("Sigil", cursorOn, player, objects);
					animationtext.add(new ClassAnimationString(""+spell_damage, cursorOn.enemy.get_location(), 20, 14, Color.BLUE));
							//cursorOn.enemy.attack_spell((int)(4*player.level),amnesia);
					player.set_player_variable("gold", player.get_player_variable("gold") + 1);
					
					if(cursorOn.enemy.current_health<1){
						add_kill_count(cursorOn.enemy, player);
						objects.remove_enemy(cursorOn.enemy);
						player.add_enemy_exp(cursorOn.enemy);
						animations.add(new ClassAnimationIterator(cursorOn.enemy.location,
								animation_loader.return_animation_by_name("animation_blackcross"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
					}else{
						animations.add(new ClassAnimationIterator(cursorOn.enemy.location,
								animation_loader.return_animation_by_name("animation_spellfireball"),ClassAnimationIterator.Constants.ANIMATION_NORMAL,1));
					}
				}else{
					refund_mana(player, spell_cost);
				}
			}
		}
		//These things should always be after the spell is cast
		if(spell_used){
			player.get_hud_animations().add(new Vector3(1,(int)spell_cost,10));
			player.get_class_mods().playerSpellMod.post_cast_modifiers(player, this);
			player.get_class_mods().playerSpellMod.hit_modifier(player, this, cursorOn, spell_damage);
		}
	}
	//This implementation ssucks
	public int predict_spell_damage(String spell_name, ClassCursorAt cursorOn, ClassCharacterPlayer player, ClassPlaceObjects objects){
		float amnesia = get_spell_strength(player);
		if (spell_name.equals("FireBall")){return cursorOn.enemy.predict_spell((int)(4*player.level),amnesia);}
		if (spell_name.equals("ManaSpark")){return cursorOn.enemy.predict_spell((int)(player.get_player_variable("current_mana")),amnesia);}
		if (spell_name.equals("Nexus")){return cursorOn.enemy.predict_spell((int)(player.get_player_variable("gold")/4),amnesia);}
		if (spell_name.equals("Klondike")){return cursorOn.enemy.predict_spell((int)(objects.get_enemies().size()*1.5),amnesia);}
		if (spell_name.equals("Sigil")){return cursorOn.enemy.predict_spell((int)(4*player.level),amnesia);}
		return 0;
	}
	public int get_spell_damage(String spell_name, ClassCursorAt cursorOn, ClassCharacterPlayer player, ClassPlaceObjects objects){
		float amnesia = get_spell_strength(player);
		if (spell_name.equals("FireBall")){return cursorOn.enemy.attack_spell((int)(4*player.level),amnesia);}
		if (spell_name.equals("ManaSpark")){return cursorOn.enemy.attack_spell((int)(player.get_player_variable("current_mana")),amnesia);}
		if (spell_name.equals("Nexus")){return cursorOn.enemy.attack_spell((int)(player.get_player_variable("gold")/4),amnesia);}
		if (spell_name.equals("Klondike")){return cursorOn.enemy.attack_spell((int)(objects.get_enemies().size()*1.5),amnesia);}
		if (spell_name.equals("Sigil")){return cursorOn.enemy.attack_spell((int)(3*player.level),amnesia);}
		return 0;
	}
	public void add_kill_count(ClassCharacterEnemy enemy, ClassCharacterPlayer player){
		player.add_god_action("did_killed");
		player.get_class_mods().playerAttackMod.increment_kill();
		if(enemy.get_attack_mod("Magic Attack")){
			player.add_god_action("magic_enemy");
		}else{
			player.add_god_action("phys_enemy");
		}
		if(enemy.get_attack_mod("Undead")){
			player.add_god_action("kill_undead");
		}else{
			player.add_god_action("kill_living");
		}
	}
	public void recalc_totems(ClassCharacterPlayer player, ClassPlaceObjects object){
		int last_health = player.health_bonus;
		player.health_bonus = 0;
		player.totem_bonus = 0;
		for(ClassObjectTotem totem:object.get_totems()){
			totem.apply_totem_bonus(player);
		}
		player.set_player_variable("current_variable", last_health);
	}

}
